﻿using AMAP.Domain;
using AMAP.ServiceClasses;
using AMAP.ServiceClasses.Common;
using AMAP.ServiceInterfaces;
using AMAP.ServiceInterfaces.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

[assembly: WebActivator.PreApplicationStartMethod(
  typeof(Automaton), "Start")]

public static class Automaton
{
    private static readonly Timer _timer = new Timer(OnTimerElapsed);
    private static readonly JobHost _jobHost = new JobHost();

    public static void Start()
    {
        _timer.Change(TimeSpan.Zero, TimeSpan.FromMilliseconds(20000));
    }

    // Here is the call of the automaton
    private static void OnTimerElapsed(object sender)
    {
        // CAUTION: Any unhandle exception will shut down the entire website!
        _jobHost.DoWork(() =>
        {
            try
            {
                IDatabaseFactory DatabaseFactory = new DatabaseFactory();
                IBasketService BasketService = new BasketService(DatabaseFactory);
                IDeliveryService DeliveryService = new DeliveryService(DatabaseFactory);
                IExternalCompositionService ExternalCompositionService = new ExternalCompositionService(DatabaseFactory);
                IExternalOrderService ExternalOrderService = new ExternalOrderService(DatabaseFactory);
                IOtherAmapService OtherAmapService = new OtherAmapService(DatabaseFactory);

                IList<ExternalOrder> ExternalOrders = ExternalOrderService.GetLastUnupdatedExternalOrder();

                OtherAmapService.UpdateExternalOrder(ExternalOrders);
                foreach (ExternalOrder ExternalOrder in ExternalOrders.Where(e => e.ProvidedQuantity >= 0))
                {
                    ExternalComposition BasketLine = ExternalCompositionService.GetByExternalOrderId(ExternalOrder.Id);

                    // Let's check if any basket has been composed with this order
                    if (BasketLine != null)
                    {
                        double BasketCount = (double)DeliveryService.GetCountBasedOnBasketId(BasketLine.BasketId);

                        double NeededQuantity = BasketLine.Quantity * BasketCount;
                        if (NeededQuantity < ExternalOrder.ProvidedQuantity)
                            ExternalOrder.RemainedQuantity = ExternalOrder.ProvidedQuantity - NeededQuantity;
                        else
                        {
                            double OldQuantity = BasketLine.Quantity;
                            BasketLine.Quantity = ExternalOrder.ProvidedQuantity / BasketCount;
                            ExternalCompositionService.UpdateWithoutSaving(BasketLine);
                            ExternalOrder.RemainedQuantity = 0;
                            EmailService.Send(
                                    "florent.henry@gmail.com",
                                    "Quantitée livrée restreinte",
                                    "Bonjour,<br /><br />" +
                                        "Troll Amap ne sera pas en mesure de fournir les quantités demandées pour le panier de cette semaine concernant le produit " + BasketLine.ExternalOrder.Product.Name + ".<br /><br />" +
                                        "La quantité livrée passe de " + BasketLine.ExternalOrder.WantedQuantity + " à " + BasketLine.ExternalOrder.ProvidedQuantity + " " + BasketLine.ExternalOrder.Unit + ".<br />" +
                                        "Par conséquent, la composition du panier pour cet article passe de " + OldQuantity + " à " + BasketLine.Quantity + " " + BasketLine.ExternalOrder.Unit + " par panier.<br /><br />" +
                                        "Cet e-mail a été envoyé automatiquement, merci de ne pas y répondre."
                            );
                        }
                    }
                    else
                        ExternalOrder.RemainedQuantity = ExternalOrder.ProvidedQuantity;
                    ExternalOrderService.UpdateWithoutSaving(ExternalOrder);
                }
                ExternalOrderService.Save();
            }
            catch (Exception) { }
        });
    }
}